;==============================================================================
; SimpleOS 32位内核 - 稳定版 + Shell功能
;==============================================================================
bits 32
org 0x1000

;==============================================================================
; 内核入口
;==============================================================================
kernel_start:
    ; 测试：立即显示一个字符，确保内核代码执行
    mov edi, 0xb8000 + 2
    mov ax, 0x0f4b          ; 'K' 白色
    mov [edi], ax
    
    call setup_idt          
    call init_pic           
    
    ; 测试：显示第二个字符
    mov edi, 0xb8000 + 4
    mov ax, 0x0f45          ; 'E' 白色
    mov [edi], ax
    
    call clear_screen
    
    ; 显示启动信息（逐行延迟显示）
    call show_boot_info
    
    ; 显示提示符
    call show_prompt
    
    ; 开启中断
    sti
    
    ; 主循环
main_loop:
    ; 检查是否有待处理的命令
    cmp byte [cmd_pending], 1
    jne .no_cmd
    mov byte [cmd_pending], 0
    
    ; 处理命令
    call process_command
    call show_prompt
    
.no_cmd:
    hlt                     
    jmp main_loop

;==============================================================================
; 显示启动信息（逐行延迟显示，带颜色）
;==============================================================================
show_boot_info:
    ; 显示系统名称（青色标题）
    mov esi, msg_system_line
    mov bl, 0x0b            ; 青色
    call print_color
    mov esi, msg_system_name
    mov bl, 0x0f            ; 白色亮
    call print_color
    mov esi, msg_system_line
    mov bl, 0x0b
    call print_color
    call boot_delay
    
    ; 显示公司信息
    mov esi, msg_info_tag
    mov bl, 0x0e            ; 黄色高亮
    call print_color
    mov esi, msg_company_text
    mov bl, 0x07            ; 灰色
    call print_color
    
    mov esi, msg_info_tag
    mov bl, 0x0e
    call print_color
    mov esi, msg_company_desc
    mov bl, 0x07
    call print_color
    call boot_delay
    
    ; 显示日期
    mov esi, msg_info_tag
    mov bl, 0x0e
    call print_color
    mov esi, msg_date_text
    mov bl, 0x07
    call print_color
    call boot_delay
    
    ; 显示版本
    mov esi, msg_info_tag
    mov bl, 0x0e
    call print_color
    mov esi, msg_version_text
    mov bl, 0x07
    call print_color
    call boot_delay
    
    ; 显示硬件检测
    mov esi, msg_sys_tag
    mov bl, 0x0e
    call print_color
    mov esi, msg_hardware_text
    mov bl, 0x07
    call print_color
    call boot_delay
    
    ; 显示GPU
    mov esi, msg_hw_tag
    mov bl, 0x0e
    call print_color
    mov esi, msg_gpu_text
    mov bl, 0x07
    call print_color
    
    mov esi, msg_hw_tag
    mov bl, 0x0e
    call print_color
    mov esi, msg_mem_text
    mov bl, 0x07
    call print_color
    call boot_delay
    
    ; 显示完成
    mov esi, msg_ok_tag
    mov bl, 0x0a            ; 绿色
    call print_color
    mov esi, msg_ready_text
    mov bl, 0x0f
    call print_color
    call boot_delay
    
    ; 显示帮助（彩色）
    mov esi, msg_help_title
    mov bl, 0x0f
    call print_color
    
    mov esi, msg_help_cmd1
    mov bl, 0x0c            ; 红色
    call print_color
    mov esi, msg_help_desc1
    mov bl, 0x07
    call print_color
    
    mov esi, msg_help_cmd2
    mov bl, 0x0c
    call print_color
    mov esi, msg_help_desc2
    mov bl, 0x07
    call print_color
    
    mov esi, msg_help_cmd3
    mov bl, 0x0c
    call print_color
    mov esi, msg_help_desc3
    mov bl, 0x07
    call print_color
    
    mov esi, msg_newline
    mov bl, 0x07
    call print_color
    
    ret

;==============================================================================
; 启动延迟（创造动态效果）
;==============================================================================
boot_delay:
    pusha
    mov ecx, 0x1000000      ; 延迟计数
.loop:
    nop
    loop .loop
    popa
    ret

;==============================================================================
; 显示提示符
;==============================================================================
show_prompt:
    mov esi, msg_prompt
    call print_string
    mov dword [input_pos], 0
    ret

;==============================================================================
; 处理命令
;==============================================================================
process_command:
    ; 检查空命令
    cmp byte [input_buffer], 0
    je .done
    
    ; 比较help命令
    mov esi, input_buffer
    mov edi, cmd_help
    call strcmp
    cmp eax, 0
    je .cmd_help
    
    ; 比较clear命令
    mov esi, input_buffer
    mov edi, cmd_clear
    call strcmp
    cmp eax, 0
    je .cmd_clear
    
    ; 比较game命令
    mov esi, input_buffer
    mov edi, cmd_game
    call strcmp
    cmp eax, 0
    je .cmd_game
    
    ; 未知命令（红色）
    mov esi, msg_unknown
    mov bl, 0x0c            ; 红色
    call print_color
    jmp .done

.cmd_help:
    ; 显示帮助（彩色）
    mov esi, msg_help_title
    mov bl, 0x0f
    call print_color
    
    mov esi, msg_help_cmd1
    mov bl, 0x0c
    call print_color
    mov esi, msg_help_desc1
    mov bl, 0x07
    call print_color
    
    mov esi, msg_help_cmd2
    mov bl, 0x0c
    call print_color
    mov esi, msg_help_desc2
    mov bl, 0x07
    call print_color
    
    mov esi, msg_help_cmd3
    mov bl, 0x0c
    call print_color
    mov esi, msg_help_desc3
    mov bl, 0x07
    call print_color
    
    mov esi, msg_newline
    mov bl, 0x07
    call print_color
    jmp .done

.cmd_clear:
    call clear_screen
    jmp .done

.cmd_game:
    ; 显示加载信息（青色）
    mov esi, msg_loading
    mov bl, 0x0b
    call print_color
    
    ; 显示进度条
    call show_progress_bar
    
    ; 启动游戏
    call start_game
    jmp .done

.done:
    ret

;==============================================================================
; 字符串比较 (ESI, EDI) 返回EAX: 0=相等
;==============================================================================
strcmp:
    push esi
    push edi
.loop:
    mov al, [esi]
    mov ah, [edi]
    cmp al, ah
    jne .not_equal
    cmp al, 0
    je .equal
    inc esi
    inc edi
    jmp .loop
.equal:
    xor eax, eax
    jmp .done
.not_equal:
    mov eax, 1
.done:
    pop edi
    pop esi
    ret

;==============================================================================
; 显示加载进度条（彩色）
;==============================================================================
show_progress_bar:
    pusha
    
    ; 显示进度条框架（青色）
    mov esi, msg_progress_bar
    mov bl, 0x0b
    call print_color
    
    ; 绘制进度条（黄色）
    mov ecx, 30                 ; 30个进度块
.progress_loop:
    push ecx
    
    ; 显示一个进度块
    mov esi, msg_progress_block
    mov bl, 0x0e            ; 黄色
    call print_color
    
    ; 延迟
    push ecx
    mov ecx, 0x500000
.delay:
    nop
    loop .delay
    pop ecx
    
    pop ecx
    loop .progress_loop
    
    ; 结束括号（青色）
    mov esi, msg_newline
    mov bl, 0x0b
    call print_color
    
    ; 显示完成消息（绿色）
    mov esi, msg_load_complete
    mov bl, 0x0a
    call print_color
    
    ; 最后延迟
    mov ecx, 0x2000000
.final_delay:
    nop
    loop .final_delay
    
    popa
    ret

;==============================================================================
; 游戏 - 3x3方块移动
;==============================================================================
start_game:
    ; 进入游戏模式
    mov byte [game_mode], 1
    
    ; 清屏并显示游戏界面（彩色）
    call clear_screen
    
    ; 标题行（青色）
    mov esi, msg_game_line
    mov bl, 0x0b
    call print_color
    
    ; 游戏名称（白色亮）
    mov esi, msg_game_title
    mov bl, 0x0f
    call print_color
    
    ; 标题行
    mov esi, msg_game_line
    mov bl, 0x0b
    call print_color
    
    ; 操作说明
    mov esi, msg_game_keys
    mov bl, 0x09            ; 蓝色
    call print_color
    mov esi, msg_game_move
    mov bl, 0x07            ; 灰色
    call print_color
    mov esi, msg_game_sep
    mov bl, 0x07
    call print_color
    mov esi, msg_game_quit_key
    mov bl, 0x09
    call print_color
    mov esi, msg_game_quit
    mov bl, 0x07
    call print_color
    
    ; 空行
    mov esi, msg_newline
    mov bl, 0x07
    call print_color
    mov esi, msg_newline
    mov bl, 0x07
    call print_color
    
    ; 初始化位置和按键（屏幕中心）
    mov dword [box_x], 38
    mov dword [box_y], 12
    mov byte [last_key], 0
    
.game_loop:
    ; 清除旧的3x3方块
    call clear_box_3x3
    
    ; 绘制新的3x3方块
    call draw_box_3x3
    
    ; 检查键盘（轮询last_key）
    mov al, [last_key]
    cmp al, 0
    je .no_key
    
    ; *** 显示读到的按键（调试用）***
    mov edi, 0xb8000 + (14 * 160) + (10 * 2)
    mov word [edi], 0x0f4b      ; K
    mov word [edi+2], 0x0f65    ; e
    mov word [edi+4], 0x0f79    ; y
    mov word [edi+6], 0x0f3a    ; :
    mov ah, 0x0c                ; 红色
    mov [edi+8], ax
    
    ; 显示ASCII码（十六进制）
    mov bl, al
    shr al, 4
    and al, 0x0f
    add al, '0'
    cmp al, '9'
    jle .hex1
    add al, 7
.hex1:
    mov ah, 0x0e
    mov [edi+12], ax
    mov al, bl
    and al, 0x0f
    add al, '0'
    cmp al, '9'
    jle .hex2
    add al, 7
.hex2:
    mov [edi+14], ax
    
    mov al, bl              ; 恢复按键值
    
    ; *** 保存按键到dl（dl不会被后续代码破坏）***
    mov dl, al
    
    ; 清除按键
    mov byte [last_key], 0
    
    ; 检查q退出
    cmp dl, 'q'
    je .exit_game
    
    ; 清除旧方块
    mov eax, [box_y]
    imul eax, 160
    mov ebx, [box_x]
    shl ebx, 1
    add eax, ebx
    mov edi, eax
    add edi, 0xb8000
    mov word [edi], 0x0f20      ; 空格
    
    ; 处理方向键（现在用dl比较）
    cmp dl, 'w'
    je .move_up
    cmp dl, 's'
    je .move_down
    cmp dl, 'a'
    je .move_left
    cmp dl, 'd'
    je .move_right
    jmp .no_key

.move_up:
    cmp dword [box_y], 3
    jle .no_key
    dec dword [box_y]
    jmp .no_key

.move_down:
    cmp dword [box_y], 22
    jge .no_key
    inc dword [box_y]
    jmp .no_key

.move_left:
    cmp dword [box_x], 0
    jle .no_key
    dec dword [box_x]
    jmp .no_key

.move_right:
    cmp dword [box_x], 76
    jge .no_key
    inc dword [box_x]

.no_key:
    ; 简单延迟
    mov ecx, 500000
.delay:
    nop
    loop .delay
    
    jmp .game_loop

.exit_game:
    ; 退出游戏模式
    mov byte [game_mode], 0
    
    call clear_screen
    call show_boot_info
    call show_prompt
    ret

;==============================================================================
; 绘制3x3方块
;==============================================================================
draw_box_3x3:
    pusha
    
    mov ecx, 3                  ; 3行
    mov esi, [box_y]
.draw_row:
    push ecx
    
    ; 计算行起始位置
    mov eax, esi
    imul eax, 160
    mov ebx, [box_x]
    shl ebx, 1
    add eax, ebx
    mov edi, eax
    add edi, 0xb8000
    
    ; 绘制3个字符
    mov word [edi], 0x0edb      ; 黄色实心块 █
    mov word [edi+2], 0x0edb
    mov word [edi+4], 0x0edb
    
    inc esi
    pop ecx
    loop .draw_row
    
    popa
    ret

;==============================================================================
; 清除3x3方块
;==============================================================================
clear_box_3x3:
    pusha
    
    mov ecx, 3                  ; 3行
    mov esi, [box_y]
.clear_row:
    push ecx
    
    ; 计算行起始位置
    mov eax, esi
    imul eax, 160
    mov ebx, [box_x]
    shl ebx, 1
    add eax, ebx
    mov edi, eax
    add edi, 0xb8000
    
    ; 清除3个字符
    mov word [edi], 0x0f20      ; 空格
    mov word [edi+2], 0x0f20
    mov word [edi+4], 0x0f20
    
    inc esi
    pop ecx
    loop .clear_row
    
    popa
    ret

;==============================================================================
; 清屏函数
;==============================================================================
clear_screen:
    pusha
    mov edi, 0xb8000
    mov ecx, 80 * 25
    mov ax, 0x0f20          
    rep stosw
    mov dword [cursor_pos], 0
    call update_cursor
    popa
    ret

;==============================================================================
; 更新硬件光标位置
;==============================================================================
update_cursor:
    pusha
    
    ; 计算光标位置 (cursor_pos / 2，因为每个字符占2字节)
    mov eax, [cursor_pos]
    shr eax, 1              ; 除以2
    
    ; 发送光标位置低8位
    mov dx, 0x3d4           ; VGA索引寄存器
    mov al, 0x0f            ; 光标位置低字节
    out dx, al
    mov dx, 0x3d5           ; VGA数据寄存器
    mov eax, [cursor_pos]
    shr eax, 1
    out dx, al
    
    ; 发送光标位置高8位
    mov dx, 0x3d4
    mov al, 0x0e            ; 光标位置高字节
    out dx, al
    mov dx, 0x3d5
    mov eax, [cursor_pos]
    shr eax, 1
    shr eax, 8              ; 取高8位
    out dx, al
    
    popa
    ret

;==============================================================================
; 打印字符串（更新cursor_pos版）- 白色
;==============================================================================
print_string:
    pusha
    mov edi, [cursor_pos]
    add edi, 0xb8000
.loop:
    lodsb
    cmp al, 0
    je .done
    cmp al, 10
    je .newline
    mov ah, 0x0f
    stosw
    jmp .loop
.newline:
    ; 换行 - 移到下一行开头
    mov eax, edi
    sub eax, 0xb8000
    add eax, 160
    mov ebx, 160
    xor edx, edx
    div ebx
    mul ebx
    mov edi, eax
    add edi, 0xb8000
    jmp .loop
.done:
    ; 更新cursor_pos
    sub edi, 0xb8000
    mov [cursor_pos], edi
    call update_cursor
    popa
    ret

;==============================================================================
; 彩色打印字符串 (ESI=字符串, BL=颜色)
;==============================================================================
print_color:
    pusha
    mov edi, [cursor_pos]
    add edi, 0xb8000
.loop:
    lodsb
    cmp al, 0
    je .done
    cmp al, 10
    je .newline
    mov ah, bl
    stosw
    jmp .loop
.newline:
    ; 换行
    mov eax, edi
    sub eax, 0xb8000
    add eax, 160
    mov ebx, 160
    xor edx, edx
    div ebx
    mul ebx
    mov edi, eax
    add edi, 0xb8000
    jmp .loop
.done:
    ; 更新cursor_pos
    sub edi, 0xb8000
    mov [cursor_pos], edi
    call update_cursor
    popa
    ret

;==============================================================================
; 设置IDT
;==============================================================================
setup_idt:
    ; 设置所有中断为默认处理程序
    mov ecx, 256
    mov edi, idt_start
    mov eax, default_isr
.loop:
    mov word [edi], ax      
    mov word [edi+2], 0x08  
    mov byte [edi+4], 0     
    mov byte [edi+5], 0x8e  
    shr eax, 16
    mov word [edi+6], ax    
    shl eax, 16
    add edi, 8
    loop .loop
    
    ; 设置键盘中断
    mov edi, idt_start + 0x21 * 8
    mov eax, keyboard_handler
    mov word [edi], ax
    mov word [edi+2], 0x08
    mov byte [edi+4], 0
    mov byte [edi+5], 0x8e
    shr eax, 16
    mov word [edi+6], ax
    
    ; 加载IDT
    lidt [idt_descriptor]
    ret

;==============================================================================
; 初始化PIC
;==============================================================================
init_pic:
    mov al, 0x11
    out 0x20, al            
    out 0xa0, al            
    
    mov al, 0x20
    out 0x21, al            
    mov al, 0x28
    out 0xa1, al            
    
    mov al, 0x04
    out 0x21, al            
    mov al, 0x02
    out 0xa1, al            
    
    mov al, 0x01
    out 0x21, al
    out 0xa1, al
    
    mov al, 0xfd            
    out 0x21, al
    mov al, 0xff            
    out 0xa1, al
    ret

;==============================================================================
; 默认中断处理程序
;==============================================================================
default_isr:
    pusha
    mov al, 0x20            
    out 0x20, al
    popa
    iret

;==============================================================================
; 键盘中断处理程序 - Shell输入版
;==============================================================================
keyboard_handler:
    pushad
    push ds
    push es
    
    ; 确保段寄存器正确
    mov ax, 0x10
    mov ds, ax
    mov es, ax
    
    ; 读取扫描码
    in al, 0x60
    
    ; 忽略按键释放
    test al, 0x80
    jnz .done_eoi
    
    ; 查找ASCII码
    movzx ebx, al
    cmp ebx, 256
    jge .done_eoi
    mov al, [scancode_table + ebx]
    test al, al
    jz .done_eoi
    
    ; 保存到last_key（供游戏使用）
    mov [last_key], al
    
    ; 检查是否在游戏模式
    cmp byte [game_mode], 1
    je .done_eoi        ; 游戏模式：只保存按键
    
    ; === Shell模式：处理输入 ===
    
    ; 处理回车键
    cmp al, 0x0a
    je .shell_enter
    
    ; 处理退格键
    cmp al, 0x08
    je .shell_backspace
    
    ; 普通字符
    cmp dword [input_pos], 78
    jge .done_eoi
    
    ; 保存到输入缓冲区
    mov ebx, [input_pos]
    mov [input_buffer + ebx], al
    inc dword [input_pos]
    
    ; 直接写显存显示
    mov edi, [cursor_pos]
    mov ah, 0x0f
    mov [0xb8000 + edi], ax
    add dword [cursor_pos], 2
    
    ; 更新硬件光标
    push eax
    mov eax, [cursor_pos]
    shr eax, 1
    mov edx, 0x3d4
    mov al, 0x0f
    out dx, al
    mov dx, 0x3d5
    mov eax, [cursor_pos]
    shr eax, 1
    out dx, al
    mov dx, 0x3d4
    mov al, 0x0e
    out dx, al
    mov dx, 0x3d5
    mov eax, [cursor_pos]
    shr eax, 1
    shr eax, 8
    out dx, al
    pop eax
    
    jmp .done_eoi

.shell_enter:
    ; 添加字符串结束符
    mov ebx, [input_pos]
    mov byte [input_buffer + ebx], 0
    
    ; 换行
    mov edi, [cursor_pos]
    mov eax, edi
    mov ebx, 160
    xor edx, edx
    div ebx
    inc eax
    mul ebx
    mov [cursor_pos], eax
    
    ; 标记需要处理命令
    mov byte [cmd_pending], 1
    jmp .done_eoi

.shell_backspace:
    cmp dword [input_pos], 0
    je .done_eoi
    dec dword [input_pos]
    
    mov edi, [cursor_pos]
    sub edi, 2
    mov word [0xb8000 + edi], 0x0f20
    mov [cursor_pos], edi
    
    ; 更新硬件光标
    push eax
    mov eax, [cursor_pos]
    shr eax, 1
    mov edx, 0x3d4
    mov al, 0x0f
    out dx, al
    mov dx, 0x3d5
    mov eax, [cursor_pos]
    shr eax, 1
    out dx, al
    mov dx, 0x3d4
    mov al, 0x0e
    out dx, al
    mov dx, 0x3d5
    mov eax, [cursor_pos]
    shr eax, 1
    shr eax, 8
    out dx, al
    pop eax
    
.done_eoi:
    mov al, 0x20
    out 0x20, al
    
    pop es
    pop ds
    popad
    iret

;==============================================================================
; 数据区
;==============================================================================
cursor_pos:     dd 0
input_pos:      dd 0
input_buffer:   times 80 db 0

; 启动信息 - 拆分以支持彩色显示
msg_system_line:  db '========================================', 10, 0
msg_system_name:  db ' RUN SHENG Edge Computing OS (RSEC-OS)', 10, 0

msg_info_tag:     db '[INFO] ', 0
msg_company_text: db 'Developer: Run Sheng Corporation', 10, 0
msg_company_desc: db 'Internal Edge Computing System', 10, 0
msg_date_text:    db 'Release Date: October 2022', 10, 0
msg_version_text: db 'Version: 10.0 (32-bit Protected Mode)', 10, 0

msg_sys_tag:      db '[SYS]  ', 0
msg_hardware_text: db 'Detecting hardware...', 10, 0

msg_hw_tag:       db '[HW]   ', 0
msg_gpu_text:     db 'GPU: NVIDIA GeForce RTX 3060', 10, 0
msg_mem_text:     db 'Memory: 128 MB RAM', 10, 0

msg_ok_tag:       db '[OK]   ', 0
msg_ready_text:   db 'System ready!', 10, 10, 0

; 命令帮助 - 拆分
msg_help_title:   db 'Available commands:', 10, 0
msg_help_cmd1:    db '  help', 0
msg_help_desc1:   db '  - Show this help', 10, 0
msg_help_cmd2:    db '  clear', 0
msg_help_desc2:   db ' - Clear screen', 10, 0
msg_help_cmd3:    db '  game', 0
msg_help_desc3:   db '  - Start game demo', 10, 0

; 游戏相关
msg_loading:      db 10, 'Loading game...', 10, 0
msg_progress_bar: db '[', 0
msg_progress_block: db '=', 0
msg_load_complete: db 'Load complete!', 10, 0

; 游戏界面 - 拆分
msg_game_line:    db '========================================', 10, 0
msg_game_title:   db '      3x3 Block Movement Game          ', 10, 0
msg_game_keys:    db '  W/A/S/D', 0
msg_game_move:    db ' - Move', 0
msg_game_sep:     db '  |  ', 0
msg_game_quit_key: db 'Q', 0
msg_game_quit:    db ' - Quit', 10, 0

msg_newline:      db 10, 0

; 其他
msg_prompt:      db 'RSEC> ', 0
msg_unknown:     db 'Unknown command. Type "help" for help.', 10, 0

; 命令字符串
cmd_help:       db 'help', 0
cmd_clear:      db 'clear', 0
cmd_game:       db 'game', 0

; 游戏变量
last_key:       db 0
game_mode:      db 0        ; 0=Shell模式, 1=游戏模式
cmd_pending:    db 0
box_x:          dd 10
box_y:          dd 10

;==============================================================================
; 扫描码转换表
;==============================================================================
scancode_table:
    db 0, 0, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', 0x08
    db 0, 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', 0x0a
    db 0, 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', "'", '`'
    db 0, '\', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/'
    times (256 - 0x36) db 0

;==============================================================================
; IDT
;==============================================================================
align 8
idt_start:
    times 256 * 8 db 0

idt_descriptor:
    dw 256 * 8 - 1          
    dd idt_start            

kernel_end:
